<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script> -->
</head>

<body>
    <div id="root">
        <div>
            <p>{{name.firstname}}</p>
            <p>{{name.lastname}}</p>
        </div>
        <p>{{message}}</p>
    </div>
    <script>
        // 实现下面的功能
        // 找到dom，遍历子节点，正则替换文本标签中的内容
        /* 
        let vue = new Vue({
            el:'#root',
            data:{
                name:'飞飞',
                message:'你好啊！'
            }
        })
        */
        // 实现存在的问题
        /*
        vue中使用的是虚拟dom
        下面是实现了单属性{{name}},vue中可以是{{child.name}}
        */

        // 本次拓展功能，实现dom和虚拟dom的互相转换
        /* 
             <div></div> {tag:'div'}
             <div class='a' title='b' id='c'></div> {tag:'div',attr:{class:a,title:b,id:c},children:[{tag:'div'}……]}
        */
        class Vue {
            constructor(options) {
                // console.log(options)
                // let {el,data} = options
                // 1.获取Dom元素-》2.获取data->3.生成一个虚拟DOM,将数据填入坑中，-》4.用虚拟dom替换原来的Dom
                this.el = options.el
                this.data = options.data
                this.exg = /\{\{(.*)\}\}/
                this.root = document.querySelector(this.el)
                // this.copyRoot = this.root.cloneNode(true)
                // 下面使用真正的虚拟DOM
                this.virDOM = GetNode(document.querySelector(this.el))
                this.Init()
                // console.dir(this.root)
            }
            Init() {
                // console.log(this.copyRoot)
                this.Complie(this.virDOM, this.data)
                // console.log(this.root)
                this.Render()
            }
            Complie(node, data) {
                let children = node.childNodes //取出子元素
                for (let i = 0; i < children.length; i++) {
                    if (children[i].nodeType === 1) { //节点元素
                        this.Complie(children[i], data)
                        // console.log('递归')
                    } else if (children[i].nodeType === 3) { //文本节点
                        let val = children[i].nodeValue
                        // console.log(val)
                        let that = this
                        val = val.replace(this.exg, function (_, e) {
                            // return that.data[e.trim()]
                            // 这里解决只能使用单层的data信息问题:使用.去划分层级
                            return that.getDate(e)
                        })
                        children[i].nodeValue = val
                    }
                }
            }
            Render() {
                // 4将虚拟dom插入到真实DOM中 ,用他的父元素调用替换子元素的方法
                this.root.parentNode.replaceChild(DOM(this.virDOM), this.root)
            }
            getDate(path) {
                // console.log(path)
                let obj = path.split(".")
                let res = this.data
                let len = obj.length
                for (let i = 0; i < len; i++) {
                    res = res[obj[i]]
                    // console.log(obj[i])
                }
                //console.log('res:',res)
                return res
            }
        }
        class Node {
            constructor(node) {
                this.tag = node.nodeName
                this.nodeType = node.nodeType
                this.nodeValue = node.nodeValue || null
                this.childNodes = []
            }
            appendChild(node) {
                this.childNodes.push(node)
            }
        }
        // 将DOM转换成虚拟DOM
        function GetNode(node) {
            let list = node.childNodes
            // console.log(list)
            let vNode = new Node(node)
            if(node.nodeType === 1){
                let list = node.childNodes
                for(let i = 0; i < list.length; i++){
                    vNode.appendChild(GetNode(list[i]))
                }
            }else{

            }
            return vNode
        }
        // 将虚拟dom转换成真实DOM
        function DOM(virDOM){
            let res = null
            if(virDOM.nodeType === 3){
                res = document.createTextNode(virDOM.nodeValue)
            }else{
                res = document.createElement(virDOM.tag)
                for(let i = 0; i < virDOM.childNodes.length; i++){
                    res.appendChild(DOM(virDOM.childNodes[i]))
                }
            }
            return res
        }
        let root = new Node(document.getElementById('root'))
        let test = GetNode(document.getElementById('root'))
        console.dir(test)
        let dom = DOM(test)
        console.log(dom)
        /* let test = document.createTextNode('123')
        let test2 = document.createElement('DIV')
        // test.nodeValue = '1234'
        console.log(test2) */
        let vue = new Vue({
            el: '#root',
            data: {
                name: {
                    firstname: '李',
                    lastname: 'hua'
                },
                message: '你好啊！'
            }
        })

    </script>
</body>

</html>